package com.baizw.cultivation.common.annotation.validator;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baizw.cultivation.common.annotation.ExistInTable;
import com.baizw.cultivation.util.OnlyOneValidUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import org.hibernate.validator.internal.engine.path.PathImpl;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ElementKind;

/**
 * 唯一校验器
 *
 * @author 剧终1204
 * @version V1.0
 * @date 2020年05月20日 9:28
 */
@Slf4j
public class ExistInTableValidator implements ConstraintValidator<ExistInTable, Object> {

    private ExistInTable existInTable;
    private String tableName;

    @Override
    public void initialize(ExistInTable constraintAnnotation) {
        this.existInTable = constraintAnnotation;
        this.tableName = StrUtil.isBlank(existInTable.tableName()) ? existInTable.value() : existInTable.tableName();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (ObjectUtil.isEmpty(value)) {
            return true;
        }
        String primaryKey = this.primaryKey(context);
        if (ArrayUtil.isArray(value)) {
            String verify = OnlyOneValidUtil.verify(tableName, primaryKey, value);
            // 禁用默认的message的值
            context.disableDefaultConstraintViolation();
            // 重新添加错误提示语句
            context.buildConstraintViolationWithTemplate(verify).addConstraintViolation();
            return StrUtil.isNotBlank(verify);
        }
        if (existInTable.mustExist()) {
            return !OnlyOneValidUtil.verifyBoolean(tableName, primaryKey, value);
        }
        return OnlyOneValidUtil.verifyBoolean(tableName, primaryKey, value);
    }

    /**
     * 获取注解中的key值
     *
     * @param context ConstraintValidatorContext
     * @return 表中的主键名称
     */
    private String primaryKey(ConstraintValidatorContext context) {
        ConstraintValidatorContextImpl validatorContext = (ConstraintValidatorContextImpl) context;
        PathImpl basePath = (PathImpl) ReflectUtil.getFieldValue(validatorContext, "basePath");
        Object currentLeafNode = ReflectUtil.getFieldValue(basePath, "currentLeafNode");
        String fieldName = (String) ReflectUtil.getFieldValue(currentLeafNode, "name");
        // ElementKind
        ElementKind kind = (ElementKind) ReflectUtil.getFieldValue(currentLeafNode, "kind");
        String primaryKey = existInTable.key();
        // 如果是Controller类型的参数注解
        if (ElementKind.PARAMETER.equals(kind)) {
            return primaryKey;
        }
        // 如果是PROPERTY类型表示被注解的是Java Bean 或者是一个属性值
        String defaultPrimaryKey = "id";
        if (defaultPrimaryKey.equals(primaryKey) && StrUtil.isNotBlank(fieldName)) {
            return fieldName;
        }
        return primaryKey;
    }
}